package com.javandad.app.client.profile;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.javandad.app.client.CodesvrParam;
import com.javandad.app.shared.FieldVerifier;
import com.javandad.app.shared.entity.User;

public class Profile implements EntryPoint {

	private TextBox usernameInput;
	private ProfileWidget profileInput;

	private ProfileServiceAsync prof = GWT.create(ProfileService.class);
	
	private boolean usernameOK = false;

	@Override
	public void onModuleLoad() {
		RootPanel panel = RootPanel.get("registrationContainer");
		if (panel != null) {
			createRegistrationForm(panel);
		} else {
			panel = RootPanel.get("ownProfileContainer");
			if (panel != null) {
				createProfileForm(panel, true, true);
			} else {
				panel = RootPanel.get("profileViewContainer");
				if (panel != null) {
					createProfileForm(panel, true, false);
				}
			}
		}
	}
	
	private void createRegistrationForm(final RootPanel reg)
	{
		prof.getUser(new AsyncCallback<User>() {
			public void onFailure(Throwable caught) {
				Window.alert("Profile: failure!\n"+caught.getMessage());
			}
			@Override
			public void onSuccess(User user) {
				createRegistrationForm(reg, user);
			}});
	}
	private void createRegistrationForm(RootPanel reg, User user) {
		VerticalPanel panel = new VerticalPanel();
		reg.add(panel);

		Label regInfo = new Label("Registration information:");
		panel.add(regInfo);
		
		createAuthenticationWidget(panel, user.getUserId());
		
		Label profileInfo = new Label("Fill out a profile:");
		panel.add(profileInfo);
		
		profileInput = new ProfileWidget(user, false, true);
		panel.add(profileInput);
		
		Button submit = new Button("Submit");
		panel.add(submit);
		panel.setCellHorizontalAlignment(submit, HasHorizontalAlignment.ALIGN_LOCALE_END);
		submit.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				submitRegistration();
			}
		});
	}

	protected void submitRegistration() {
		final String username = usernameInput.getText();
		if(!usernameOK)
		{
			String msg = "You can't take username "+username+".";
			Window.alert(msg);
			return;
		}
		profileInput.updateUserData();
		User user = profileInput.getUser();
		user.setUsername(username);
		prof.registerNewUser(user, new AsyncCallback<String>() {

			@Override
			public void onFailure(Throwable caught) {
				Window.alert("submit failure\n"+caught.getMessage());
			}

			@Override
			public void onSuccess(String err) {
				if (err == null) {
					Window.alert(username + " was successfully registered.");
					Window.open("home.jsp?"+CodesvrParam.getCodesvrParam(), "_self", "");
				} else {
					Window.alert("Error registering " + username + ":\n"+err);
				}
			}
		});
	}

	private void createAuthenticationWidget(Panel parent, String account) {
		final FlexTable ft = new FlexTable();
		parent.add(ft);
		int row = 0;
		
		ft.setText(row, 0, "OpenID account:");
		ft.setText(row, 1, account);
		
		row++;
		final int usernameRow = row;
		ft.setText(usernameRow, 0, "username:");
		usernameInput = new TextBox();
		usernameInput.setName("username");
		ft.setWidget(usernameRow, 1, usernameInput);
		usernameInput.addChangeHandler(new ChangeHandler() {
			@Override
			public void onChange(ChangeEvent event) {
				final String username = usernameInput.getText();
				if(!FieldVerifier.isValidUsername(username))
				{
					usernameOK = false;
					ft.setText(usernameRow, 2, "username " + username + " is not valid.");
					return;
				}
				prof.userExists(username, new AsyncCallback<Boolean>() {
					public void onFailure(Throwable caught) {
						ft.setText(usernameRow, 2, "Error checking username " + username + "!");
					}
					public void onSuccess(Boolean result) {
						if (result)
							ft.setText(usernameRow, 2, "username " + username + " already taken :(");
						else
							ft.setText(usernameRow, 2, "username " + username + " is free :)");
						usernameOK = !result;
					}
				});
			}
		});
	}

	private void createProfileForm(final Panel panel, final boolean viewable, final boolean editable) {
		AsyncCallback<User> userDisplayer = new AsyncCallback<User>() {
			@Override
			public void onFailure(Throwable caught) {
				Window.alert("Profile: failure!");
			}
			@Override
			public void onSuccess(User result) {
				createProfileForm(panel, viewable, editable, result);
			}};
			
		if(editable)
		{
			// user is viewing his own resume, get the logged-in user and display his information.
			prof.getUser(userDisplayer);
		}
		else
		{
			// user is viewing someone else's resume. 
			// viewed user is given as http-get parameter "username".
			// query server about this user's info and display it.
			String username = Window.Location.getParameter("view");
			prof.getUser(username, userDisplayer);
		}
	}
	private void createProfileForm(Panel panel, boolean viewable, boolean editable, User user)
	{
		ProfileWidget editor = new ProfileWidget(user, viewable, editable);
		panel.add(editor);
		editor.addUserChangeHandler(new ProfileWidget.UserChangeHandler() {
			public void userChanged(User user) {
				prof.changeUser(user, new AsyncCallback<Boolean>() {
					public void onFailure(Throwable caught) {
						Window.alert("Update user failure!");
					}
					public void onSuccess(Boolean result) {
						Window.alert("User successfully updated.");
					}});
			}
		});
	}

}
